home *** CD-ROM | disk | FTP | other *** search
- /*
- SWITCH_C - QL-Kermit protocol state switcher
-
- Based on ckcpro.w, (C) Columbia University
- */
-
-
- /* Include files */
-
- #include "ram1_ker_h" /* Kermit definitions */
-
- #include "flp1_fcntl_h" /* File opening modes */
-
-
- /* External variables */
-
- extern int size; /* Current packet size */
- extern int n; /* Current packet number */
- extern int numtry; /* Retry count */
- extern int oldtry; /* Saved retry count */
- extern int debug; /* Debugging level */
- extern int retry; /* Retry limit */
-
- extern long filein; /* File bytes received */
- extern long fileout; /* File bytes sent */
- extern long totin; /* Batch bytes received */
- extern long totout; /* Batch bytes sent */
-
- extern bool toscr; /* Flag for screen output */
-
- extern char sndpkt[]; /* Send packet data */
- extern char recpkt[]; /* Received packet data */
- extern char *newfilnam; /* Name of file created */
- extern char *destdev; /* Default destination device */
- extern char *sourdev; /* Default source device */
- extern char *errdata; /* Data for E packet */
-
- extern char stype; /* Server command */
- extern char type; /* Current packet type */
-
- extern char *cmarg,*cmarg2; /* Command arguments */
-
- extern int fp; /* Transfer file */
-
- extern int _oserr; /* QDOS error code */
- extern int oserr; /* Copy of above */
-
- extern bool warn8; /* Lost 8th bit warning given */
- extern bool cxseen; /* File interrupt flag */
- extern bool czseen; /* Batch interrupt flag */
-
- extern int state; /* Current state */
-
-
- /* External functions */
-
- extern char *stname(); /* Printable state name */
-
-
- /* Local variables */
-
- int num; /* Packet number */
- int len; /* Packet length */
- int pt; /* Packet type */
-
- static char ackd; /* Y packet data */
-
-
- /* Switcher macros */
-
- #define CHKTRY if (numtry++>retry) RERR
- #define SWREC switch (pt = rpack(&len,&num,recpkt))
-
- #define NNXT n = (n+1)%64
-
- #define NEXT(s) return(s)
- #define STAY return(state)
-
- #define GOT(c) case 'c':
- #define OTHER default:
- #define NONE case BAD:
- #define INTRPT case INTE:
-
- #define DONE return(COMP)
- #define STOP return(ABORT)
- #define QERR return(qdoserr())
- #define PERR return(proterr())
- #define IERR return(interrupt())
- #define RERR return(rtlim())
-
-
- /* SWITCHER - The state table switcher for all the Kermit actions. It loops
- until either it finishes, or an error is encountered. The routines
- called by switcher are responsible for changing the state, although the
- choice of which new state may also be influenced by the current
- Kermit command. The entry state is set by the user's command.
- */
-
- bool switcher(start)
- int start;
- {
- newfilnam[0] = '\0'; /* Set up file name */
- n = 0; /* Initialize packet number */
- numtry = 0; /* No retries yet */
- tinit(); /* Set up default Send-Init values */
-
- state = start; /* Set up starting state */
-
- flushinput(); /* Start each transaction clean */
-
- forever /* Do this as long as necessary */
- {
- if (debfull) debugst(); /* Log state and packet number */
- if (state==ABORT) closef(); /* Clean up mess */
-
- switch (state)
- {
-
- case ABORT: return(FALSE); /* Abort */
- case COMP: return(TRUE); /* Complete */
- case R_INIT: state = rinit(); endcase; /* Receive-Init */
- case R_FILE: state = rfile(); endcase; /* Receive-File */
- case R_DATA: state = rdata(); endcase; /* Receive-Data */
- case S_INIT: state = sinit(); endcase; /* Send-Init */
- case S_FILE: state = sfile(); endcase; /* Send-File */
- case S_DATA: state = sdata(); endcase; /* Send-Data */
- case S_EOF: state = seof(); endcase; /* Send-End-of-File */
- case S_BRK: state = sbreak(); endcase; /* Send-Break */
- case S_COMD: state = scomd(); endcase; /* Send-Command */
- case G_INIT: state = ginit(); endcase; /* Get-Init */
- case K_ERR: state = serr(); endcase; /* Send-Error */
-
- default: error("Bad protocol state - %d",state);
- return(FALSE); /* Unknown state, fail */
- }
- }
- }
-
-
- /* SERR - Send an error packet to remote machine */
-
- int serr()
- {
- if (*errdata=='\0') /* If no error message, */
- strcpy(errdata,"No description"); /* put in a default one */
- spack('E',n,strlen(errdata),errdata); /* Send the error packet */
- STOP; /* and end transaction */
- }
-
-
- /* SCOMD - Send generic or system command to server */
-
- int scomd()
- {
- int l;
-
- CHKTRY; /* Check retries */
- printf("Sending command\n");
-
- len = stclen(cmarg); /* Get length of command name */
- spack(stype,0,len,cmarg); /* Send command packet */
- SWREC /* What was the reply? */
- {
-
- GOT(Y) if (stype=='G') DONE; /* Back to parser */
- STAY; /* Try again otherwise */
-
- GOT(S) rpar(recpkt);
- l = spar(sndpkt);
- spack('Y',n++,l,sndpkt); /* Get ready to receive */
- toscr = TRUE; /* onto screen */
- NEXT(R_DATA); /* any command output */
-
- GOT(E) prerrpkt(recpkt); /* Error, print message */
- STOP;
-
- GOT(N) STAY; /* NAK from server, keep trying */
-
- GOT(B) if (num!=n) STOP; /* Need right packet number here */
- ack(); /* Say OK */
- STAY; /* and keep trying */
-
- NONE nak(); /* Appease server to avoid error */
- STAY; /* and try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* GINIT - Ask server for file */
-
- int ginit()
- {
- int l;
-
- CHKTRY; /* Check retries */
- printf("Asking server for %s\n",cmarg);
-
- len = stclen(cmarg);
- spack('R',0,len,cmarg); /* Send an R packet */
- SWREC /* What was the reply? */
- {
-
- GOT(S) rpar(recpkt); /* Get the other side's init data */
- l = spar(sndpkt); /* Fill up packet with mine */
- spack('Y',n,l,sndpkt); /* and ACK with my parameters */
- NNXT;
- oldtry = numtry; /* Save old try count */
- numtry = 0; /* Start a new counter */
- NEXT(R_FILE); /* and enter Get-File state */
-
- GOT(E) closef(); /* Clean up transfer file */
- discard(newfilnam); /* and delete it */
- prerrpkt(recpkt); /* Print error message */
- STOP;
-
- GOT(N) STAY; /* NAK from server, keep trying */
-
- GOT(B) if (num!=n) STOP; /* Need right packet number here */
- ack(); /* Say OK */
- STAY; /* and keep trying */
-
- NONE nak(); /* Appease server to avoid error */
- STAY; /* and try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* RINIT - Receive Initialization */
-
- int rinit()
- {
- int l;
-
- CHKTRY; /* Check retries */
- printf("Exchanging parameters\n");
-
- SWREC /* Get a packet */
- {
-
- GOT(S) rpar(recpkt); /* Get the other side's init data */
- l = spar(sndpkt); /* Fill up packet with mine */
- spack('Y',n,l,sndpkt); /* and ACK with my parameters */
- oldtry = numtry; /* Save old try count */
- numtry = 0; /* Start a new counter */
- NNXT;
- NEXT(R_FILE); /* and enter Receive-File state */
-
- GOT(E) closef(); /* Clean up file */
- discard(newfilnam); /* and delete it */
- prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE nak(); /* Return a NAK */
- STAY; /* and keep trying */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* RFILE - Receive File Header */
-
- int rfile()
- {
- int l;
- char file[30];
-
- CHKTRY; /* Check retries */
-
- SWREC /* Get a packet */
- {
-
- GOT(S) if (oldtry++>retry) RERR; /* Check retries */
- if (num==((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
- { /* Yes, ACK it again with */
- l = spar(sndpkt); /* our Send-Init parameters */
- spack('Y',num,l,sndpkt);
- numtry = 0; /* Reset try counter */
- STAY;
- }
- else STOP; /* Not previous packet */
-
- GOT(Z) if (oldtry++>retry) RERR; /* Check retries */
- if (num==((n==0) ? 63 : n-1)) /* Previous packet, mod 64? */
- { /* Yes, ACK it again */
- ackn(num);
- numtry = 0;
- STAY;
- }
- else STOP; /* Not previous packet */
-
- GOT(F) if (num!=n) STOP; /* Must have right packet number */
-
- if (strlen(cmarg2)==0) rtol(file,recpkt);
- else strcpy(file,cmarg2); /* Make new file name */
-
- if ((fp = devopen(file,destdev,O_WRONLY|O_CREAT|O_TRUNC))<0)
- {
- error("Cannot create %s for receiving",file);
- QERR;
- }
-
- printf("Receiving %s as %s\n",recpkt,newfilnam);
- ack(); /* Acknowledge the file header */
- oldtry = numtry; /* Reset try counters */
- numtry = 0;
- toscr = FALSE; /* Data into a file */
- filein = 0; /* Clear byte counter */
- NNXT;
- NEXT(R_DATA); /* Switch to Data state */
-
- GOT(X) if (num!=n) STOP; /* Screen data is coming */
- toscr = TRUE; /* Set data destination */
- bufemp(recpkt,len); /* Write the data to screen */
- ack(); /* Acknowlege it */
- oldtry = numtry; /* Reset the try counters */
- numtry = 0;
- NNXT;
- NEXT(R_DATA); /* and continue to receive data */
-
- GOT(B) if (num!=n) STOP; /* Need right packet number here */
- ack(); /* Say OK */
- printf("Received EOT, total %ld bytes\n",totin);
- n = 0; /* Reset packet counter */
- DONE; /* and finish transaction */
-
- GOT(E) closef(); /* Clean up file */
- discard(newfilnam); /* and delete it */
- prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE nak(); /* Return a NAK */
- STAY; /* and keep trying */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* RDATA - Receive Data */
-
- int rdata()
- {
- CHKTRY; /* Check retries */
-
- SWREC /* Get a packet */
- {
-
- GOT(D) if (num!=n) /* Right packet number? */
- {
- if (oldtry++>retry) RERR; /* Check retries */
- if (num==((n==0) ? 63 : n-1)) /* Check packet number */
- { /* Previous packet again? */
- ackn(num); /* Yes, re-ACK it */
- numtry = 0; /* Reset try counter */
- STAY; /* Don't write out data! */
- }
- else STOP; /* Not previous packet */
- }
-
- if (!bufemp(recpkt,len)) /* Write the data to file or screen */
- {
- error("Write failure");
- QERR;
- }
-
- if (cxseen) ack1("X"); /* Check interrupt flags */
- else if (czseen) ack1("Z"); /* and send an */
- else ack(); /* appropriate acknowlegement */
-
- oldtry = numtry; /* Reset the try counters */
- numtry = 0;
- NNXT;
- STAY;
-
- GOT(F) if (oldtry++>retry) RERR; /* Check retries */
- if (num==((n==0) ? 63 : n-1)) /* Check packet number */
- {
- ackn(num); /* ACK previous one again */
- numtry = 0; /* Reset try counter */
- STAY;
- }
- else STOP; /* Not previous packet */
-
- GOT(Z) if (num!=n) STOP; /* Must have right packet number */
- ack(); /* OK, ACK it */
- printf("Received EOF, %ld bytes\n",filein);
- totin += filein;
- if (!toscr)
- {
- closef(); /* Close the file */
- if (*recpkt=='D') /* Check for 'discard file' */
- {
- discard(newfilnam);
- printf("File discarded by %s interrupt\n",(cxseen || czseen) ? "local" : "remote");
- }
- }
- toscr = FALSE; /* Reset disposition flag */
- NNXT;
- NEXT(R_FILE); /* and go back to Receive-File state */
-
- GOT(E) closef(); /* Tidy up file */
- discard(newfilnam); /* and delete it */
- prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE nak(); /* Return a NAK */
- STAY; /* and keep trying */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* SINIT - send this side's parameters and get other side's back */
-
- int sinit()
- {
- int l;
-
- CHKTRY; /* Check retries */
- printf("Exchanging parameters\n");
-
- l = spar(sndpkt); /* Fill up init info packet */
- spack('S',n,l,sndpkt); /* Send an S packet */
- SWREC /* What was the reply? */
- {
-
- GOT(N) STAY; /* NAK, try it again */
-
- GOT(Y) if (n!=num) STAY; /* If wrong ACK, try again */
- rpar(recpkt); /* Get other side's init info */
- numtry = 0; /* Reset try counter */
- NNXT;
- NEXT(S_FILE); /* and switch state to Send-File */
-
- GOT(E) prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE STAY; /* Receive failure, try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* SFILE - Send File Header */
-
- int sfile()
- {
- char file[30]; /* Name file is sent under */
-
- CHKTRY; /* Check retries */
- closef(); /* Ensure last file closed */
-
- if ((fp = devopen(cmarg,sourdev,O_RDONLY))<0)
- { /* Open transfer file */
- error("Cannot open %s for sending",cmarg);
- QERR;
- }
-
- if (strlen(cmarg2)==0) ltor(file,newfilnam); /* No remote name, use local one */
- else strcpy(file,cmarg2); /* Remote name given, use that */
-
- len = strlen(file); /* Get length of new filename */
- printf("Sending %s as %s\n",newfilnam,file);
-
- warn8 = FALSE; /* Clear 8-bit warning flag, */
- ackd = ' '; /* remote interrupt flag */
- cxseen = FALSE; /* and file interrupt flag */
- fileout = 0; /* Reset character count */
-
- spack('F',n,len,file); /* Send an F packet */
-
- SWREC /* What was the reply? */
- {
-
- GOT(N) num = (--num<0 ? 63 : num); /* NAK, just stay in this state */
- if (n!=num) STAY; /* unless it's NAK for next packet, */
- /* which is just like an ACK for */
- /* this packet so fall through */
-
- GOT(Y) if (n!=num) STAY; /* If wrong ACK, stay here */
- numtry = 0; /* Reset try counter */
- NNXT;
- size = bufill(sndpkt); /* Get first data from file */
- NEXT(S_DATA); /* and switch to sending state */
-
- GOT(E) prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE STAY; /* Receive failure, try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* SDATA - Send File Data */
-
- int sdata()
- {
- char r; /* Temporary */
-
- CHKTRY; /* Check retries */
-
- if (cxseen || czseen) NEXT(S_EOF); /* Interrupt from this end? */
-
- spack('D',n,size,sndpkt); /* Send a D packet */
- SWREC /* What was the reply? */
- {
-
- GOT(N) num = (--num<0 ? 63 : num); /* NAK, just stay in this state */
- if (n!=num) STAY; /* unless it's NAK for next packet */
- /* which is just like an ACK for */
- /* this packet so fall through */
-
- GOT(Y) if (n!=num) STAY; /* If wrong ACK, try again */
- numtry = 0; /* Reset try counter */
- NNXT;
-
- if ((r = recpkt[0])=='X' || r=='Z') /* Interrupt from remote end? */
- {
- ackd = r; /* Yes, save interrupt type */
- NEXT(S_EOF); /* and go to send Z/D */
- }
-
- size = bufill(sndpkt); /* Get data from file */
- if (size==EOF) NEXT(S_EOF); /* If EOF set state to that */
- else STAY; /* Got data, stay in send state */
-
- GOT(E) prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE STAY; /* Receive failure, try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* SEOF - Send End-Of-File */
-
- int seof()
- {
- CHKTRY; /* Check retries */
-
- if (cxseen || czseen || ackd=='X' || ackd=='Z')
- printf("Sending discard (%s interrupt)\n",(cxseen || czseen) ? "local" : "remote");
- else printf("Sending EOF, %ld bytes\n",fileout);
- totout += fileout;
-
- if (debon) printf("Closing input file\n");
- closef(); /* Close the input file */
-
- if (cxseen || czseen || ackd=='X' || ackd=='Z') spack('Z',n,1,"D");
- else spack('Z',n,0,0); /* Send appropriate EOF */
-
- SWREC /* What was the reply? */
- {
-
- GOT(N) num = (--num<0 ? 63 : num); /* NAK, just stay in this state */
- if (n!=num) STAY; /* unless it's NAK for next packet, */
- /* which is just like an ACK for */
- /* this packet so fall through */
-
- GOT(Y) if (n!=num) STAY; /* If wrong ACK, try again */
- numtry = 0; /* Reset try counter */
- NNXT;
- NEXT(S_BRK); /* then finish transaction */
-
- GOT(E) prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE STAY; /* Receive failure, try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* SBREAK - Send Break (end of transaction) */
-
- int sbreak()
- {
- CHKTRY; /* Check retries */
- printf("Sending EOT, total %ld bytes\n",totout);
-
- spack('B',n,0,0); /* Send a B packet */
- SWREC /* What was the reply? */
- {
-
- GOT(N) num = (--num<0 ? 63 : num); /* NAK, just stay in this state */
- if (n!=num) STAY; /* unless it's NAK for next packet, */
- /* which is just like an ACK for */
- /* this packet so fall through */
-
- GOT(Y) if (n!=num) STAY; /* If wrong ACK, try again */
- numtry = 0; /* Reset try counter */
- NNXT;
- DONE; /* Transaction complete */
-
- GOT(E) prerrpkt(recpkt); /* Print error message */
- STOP;
-
- NONE STAY; /* Receive failure, try again */
-
- INTRPT IERR; /* CTRL-E interrupt */
-
- OTHER PERR; /* Some other packet type */
-
- }
- }
-
-
- /* DEBUGST - Log the state & expected packet number */
-
- debugst()
- {
- printf("State %s, packet %d\n",stname(state),n);
- }
-
-
- /* PROTERR - An unexpected packet type received */
-
- int proterr()
- {
- printf("PROTOCOL ERROR: %c packet in state %s\n",pt,stname(state));
- strcpy(errdata,"Protocol error");
- return(K_ERR);
- }
-